/*
 * Copyright 2008,2009,2010 Daniel Freitas
 * 
 * This file is part of DMF Generic DAO.
 * 
 * DMF Generic DAO is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General
 * Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
 * later version.
 * 
 * DMF Generic DAO is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU Lesser General Public License along with DMF Generic DAO. If not, see
 * <http://www.gnu.org/licenses/>.
 */
package com.googlecode.dmf.genericdao.spring.scanners;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;

/**
 * A package scanner scans for classes in a given package and returns {@link Class} objects for every class it could
 * find and initialize. Since the reflection API is not able to list all classes under a given package, the scan has to
 * be performed by an actual search on the file system (whether it is remote or not) for .class files.
 * 
 * @author <a href="mailto:daniel.mfreitas@gmail.com">Daniel Freitas</a>
 * 
 */
public interface IPackageScanner {

    /**
     * Given a {@link URI}, attempts to obtain {@link Class} information for every Java class under the path denoted by
     * the URI in which the package matches the provided base package. Classes in subpackages of the base package must
     * also be included.
     * <p/>
     * Implementations of this interface should use the thread's context class loader to obtain the {@link Class}
     * instances.
     * 
     * @param rootPath
     *            The path to scan for Java classes.
     * @param basePackage
     *            The package to be used as a matcher reference for the loaded classes.
     * @return A list with all Java classes under the provided path which the package matches the provided base package.
     *         Classes in subpackages of the base package must also be included.
     * @throws IOException
     *             If unable to access or read information from the denoted path.
     * @throws URISyntaxException
     *             If an error occur while manipulating the URIs to the resources.
     */
    List<Class<?>> scan(final URI rootPath, final String basePackage) throws IOException, URISyntaxException;

    /**
     * Given a URI for a package in the classpath, returns a URI for the "container" where the resource is located. A
     * base package name can be provided to be used as a hint to help identify where the top level container path
     * starts. This information will be used as the <tt>rootPath</tt> of the {@link IPackageScanner#scan(URI, String)}
     * method.
     * <p/>
     * For example, a resource URI of <tt>file:/path/to/res/com/somepackage</tt> and a base package of
     * <tt>com.somepackage</tt>, yields the URI <tt>file:/path/to/res</tt>. If the base package was an empty string then
     * the URI would be the same as the input URI.
     * <p/>
     * As another example, if the resource is inside a jar file, then the URI
     * <tt>jar:file:/path/to/lib.jar!com/somepackage</tt> should produce the URI <tt>file:/path/to/lib.jar</tt>. Note
     * that in this example the base package is not necessary since classpath resources in jar files can be easily
     * parsed due to the presence of the exclamation mark to separate the package from the jar file location.
     * 
     * @param pscksgeResourceUri
     *            The {@link URI} for a package in the classpath.
     * @param basePackage
     *            A base package to be used as a hint to help identify the top level container where the resource is
     *            located. See examples above.
     * 
     * @return A {@link URI} for the location of the top level container for the package.
     * 
     * @throws URISyntaxException
     *             If there's an error while producing the resulting URI.
     */
    URI extractResourceContainerUri(final URI pscksgeResourceUri, final String basePackage) throws URISyntaxException;

    /**
     * Returns the name of the protocol this scanner understands and knows how to extract class information from.
     * Examples include <tt>file</tt> for a resource of type <tt>file:/path/to/resource</tt> and <tt>jar</tt> for
     * <tt>jar:file:/path/to/file.jar!/com/somepackage</tt>
     * 
     * @return The protocol this scanner understands and knows how to extract class information from.
     */
    String supportsProtocol();
}